package org.demo.test.socket.server;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.MessageToMessageDecoder;
import io.netty.handler.codec.MessageToMessageEncoder;
import io.netty.handler.codec.bytes.ByteArrayDecoder;
import io.netty.handler.codec.bytes.ByteArrayEncoder;
import io.netty.handler.codec.serialization.ObjectDecoderInputStream;
import io.netty.handler.codec.serialization.ObjectEncoderOutputStream;
import io.netty.util.AttributeKey;
import io.netty.util.concurrent.DefaultThreadFactory;

import java.io.ByteArrayInputStream;
import java.util.List;
import java.util.concurrent.ThreadFactory;

import org.apache.log4j.Logger;
import org.demo.test.socket.User;

public class NettySocketServer {

	public static void main(String[] args) {
		// 主服务启动器
		ServerBootstrap serverBootstrap = new ServerBootstrap();
		// boss线程池
		EventLoopGroup bossLoopGroup = new NioEventLoopGroup(1);
		
		// work线程池
		ThreadFactory threadFactory = new DefaultThreadFactory("Work thread pool");
		int processorNum = Runtime.getRuntime().availableProcessors();
		EventLoopGroup workLoopGroup = new NioEventLoopGroup(processorNum*2,threadFactory);
		// 
		serverBootstrap.group(bossLoopGroup,workLoopGroup);
		
		// 设置服务的通道类型
		serverBootstrap.channel(NioServerSocketChannel.class);
		serverBootstrap.childHandler(new ChannelInitializer<NioSocketChannel>() {
			@Override
			protected void initChannel(NioSocketChannel ch) throws Exception {
				ch.pipeline().addLast(new MessageToMessageEncoder<User>() {
					@Override
					protected void encode(ChannelHandlerContext ctx, User msg, List<Object> out) throws Exception {
						System.out.println("encode:"+msg);
						out.add(msg);
					}
				});
				ch.pipeline().addLast(new MessageToMessageDecoder<ByteBuf>() {
					@Override
					protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws Exception {
						System.out.println("decode:"+msg.toString());
						byte[] b = new byte[msg.readableBytes()];
						msg.readBytes(b);
						ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(b);
						ObjectDecoderInputStream objectDecoderInputStream = new ObjectDecoderInputStream(byteArrayInputStream);
						out.add(objectDecoderInputStream.readObject());
					}
				});

//				ch.pipeline().addLast(new ByteArrayDecoder());
//				ch.pipeline().addLast(new ByteArrayEncoder());
				ch.pipeline().addLast(new TCPServerHandler());

			}
		});
		
		// 设置服务器绑定的端口IP
		serverBootstrap.option(ChannelOption.SO_BACKLOG, 123);
		serverBootstrap.childOption(ChannelOption.SO_KEEPALIVE, true);
		serverBootstrap.bind("0.0.0.0", 6666);
		//serverBootstrap.bind("0.0.0.0", 6667);
	}
}

class TCPServerHandler extends ChannelInboundHandlerAdapter{

	Logger logger = Logger.getLogger(TCPServerHandler.class);
	
	private static AttributeKey<StringBuffer> content = AttributeKey.valueOf("content");
	
	@Override
	public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
		logger.info("channelRegistered 注册!");
	}

	@Override
	public void channelActive(ChannelHandlerContext ctx) throws Exception {
		logger.info("channelRegistered 激活!");
	}

	@Override
	public void channelInactive(ChannelHandlerContext ctx) throws Exception {
		// TODO Auto-generated method stub
		super.channelInactive(ctx);
	}

	/*@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg)
			throws Exception {
		ByteBuf bb = (ByteBuf)msg;
		try{
			StringBuffer sb = new StringBuffer();
			while(bb.isReadable()){
				sb.append((char)bb.readByte());
			}
			StringBuffer con = ctx.attr(content).get();
			if(con == null){
				con = new StringBuffer();
				ctx.attr(content).set(con);
			}
			con.append(sb);
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			bb.release();
		}
	}*/

	@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg)
			throws Exception {
		System.out.println(msg);
		User bb = (User)msg;
		System.out.println(bb);
	}

	@Override
	public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
		// TODO Auto-generated method stub
		super.channelReadComplete(ctx);
	}
	
}
